/*********************************************
 *Flow control over WiFi and UART for ESP8266.
 *Author: openthings@163.com. 
 *copyright&GPL V2.
 *Last modified 2014-10-20.
 **********************************************/

#include "c_types.h"
#include "user_interface.h"
#include "xc_version.h"
#include "espconn.h"
#include "mem.h"
#include "xc.h"
//#include "xc_ipCmd.h"
#include "osapi.h"
#include "driver/uart.h"
#include "xc_flow.h"
#include "wix_tcpserver.h"

//extern void ICACHE_FLASH_ATTR		tcpserver_send(char *pbuf, unsigned short length);

extern void xc_cmd_onCmd(char* pCMD);				//执行控制指令。可以来自于串口或WiFi。

bool xc_flow_cmdPrefix = false;
bool xc_flow_cmdFlag = false;
uint8_t xc_flow_cmdBuffer[256];
uint16_t xc_flow_cmdIndex = 0;

#define xc_flow_Max 256
uint8_t xc_flow_Buffer[xc_flow_Max];
uint16_t xc_flow_Index = 0;

/******************************************************
*x-flow：数据透明传输体制，避免控制和透传模式切换。
*^@CWMODE=1^,在透传数据流中嵌入控制指令，动态处理。
*嵌入指令被截获、提取、处理，其它数据按照透传交换处理。
*调用关系如下：
	串口数据流\
		  \			{->onCMD->onCmdAT
		  \onFlowReceiveing()			onCMDUser
		  /			{->onData->sendToWifi
		  /					sendToUart
	WiFi数据流/
*******************************************************/
void xc_flow_BufferClean()
{
	os_memset(xc_flow_Buffer,xc_flow_Max);
}
/******************************************************
 *接收串口数据，对输入字符进行合并为char*类型。
 *接收到串口中断来的数据。
 *******************************************************/
void xc_flow_onUart(uint8_t a_uart) {	
	//回显接收到的字符。
	uart_tx_one_char(a_uart);

	if (a_uart=='\n') return;	//扔掉多余的换行符。
	if (a_uart=='\r') {			//判断行结束符。
		xc_flow_Buffer[xc_flow_Index] = '\0';	//接收字符串结束。
		xc_flow_Index = 0 ;
		xc_flow_onUartReceiving(xc_flow_Buffer);
		xc_flow_BufferClean();							//reset xc_flow_Buffer
	}
	else	{
		xc_flow_Buffer[xc_flow_Index] = a_uart;
		xc_flow_Index ++;
		//缓冲区慢，重置。
		if (xc_flow_Index >= xc_flow_Max)	{
			xc_flow_Buffer[xc_flow_Index-1] = '\0';
			xc_flow_Index = 0 ;
			xc_flow_onUartReceiving(xc_flow_Buffer);
		}
	}
}

//按行处理来自串口的数据。
void xc_flow_onUartReceiving(char* struart) {
	xc_flow_onFlowFilter(struart);
	xc_flow_sendtoWifi(struart);
}

/******************************************************
 *接收到WiFi传来的数据。
 ******************************************************/
void xc_flow_onWifiReceiving(char* strwifi) {
	//直接发送到串口。
	//sendInfo("REV:");
	//sendInfo(strwifi);
	//如果超过缓冲区长度，可能缺失结束符。强制结束，以免溢出。
	if (strlen(strwifi)>xc_flow_Max) {
		strwifi[xc_flow_Max-1] = '\0';
	}
	strcpy(xc_flow_Buffer,strwifi);

	xc_flow_onFlowFilter(xc_flow_Buffer);
	xc_flow_sendtoUart(xc_flow_Buffer);
}

/******************************************************
 *接收到WiFi和串口传来的数据，分离出指令和数据。
 *指令调用onCMD，数据调用onData.
 ******************************************************/
void xc_flow_onFlowFilter(char* strdata)
{
	//char temp[64];
	//os_sprintf(temp, "XCMD: %s\r\n",strdata);
	//sendInfo(temp);

	if (strdata[0]=='@') {
		sendInfo("GOT CMD.\r\n");
		xc_cmd_onCmd(strdata);
		return ;
	}
	//非本地指令数据。
	xc_flow_onData(strdata);	
}

/******************************************************
 *除指令外的其他数据处理，一般做透明交换。
 *需判断字符串的有效性，只处理允许的字符集合。
 ******************************************************/
void xc_flow_onData(char* strdata)
{
	if (strdata[0]=='\0') return;			//多发送的空字符串？
	if (strdata[0]=='\r') return;			//扔掉多余的换行符。
	if (strdata[0]=='\n') return;			//扔掉多余的换行符。

	sendInfo("DATA: ");
	sendInfo(strdata);
	sendInfo("\r\n");
}

/******************************************************
 *串口数据转发到WiFi端口。
 ******************************************************/
void xc_flow_sendtoWifi(char* strdata)
{
	unsigned short nLen = strlen(strdata);

	//TCP发送。
	tcpserver_send(strdata,nLen);
	//tcpclient_send(strdata,nLen);
	
	//UDP发送。
	//udpserver_send(strdata,nLen);
	//udpclient_send(strdata,nLen);
}

/*****************************************************
 *WiFi端口数据转发到串口。
 *****************************************************/
void xc_flow_sendtoUart(char* strdata)
{
	uart0_sendStr(strdata);
}

/******************************************************
 *发送调试信息到串口。 
 ******************************************************/
//发送字符串到串口。
void sendInfo(char* strInfo) {
  uart0_sendStr(strInfo);
}

//发送字符串到串口，加回车换行。
void sendInfoln(char* strInfo) {
  uart0_sendStr(strInfo);
  uart0_sendStr("\r\n");
}

//发送字符串到串口和WiFi.
void sendInfoAll(char* strInfo) {
	uart0_sendStr(strInfo);
	//uart0_sendStr("\r");
	xc_flow_sendtoWifi(strInfo);
	//xc_flow_sendtoWifi("\r");
}





